# -*- coding: utf-8 -*-
#Autor: Vitor Letras n.º 3947
#Data: 11-11-2013

"""
Neste modulo é efectuada a leitura do ficheiro cna131fresultados.xls
e preenchida uma base de dados com o nome cna131fresultadosdb.
"""

import csv
import pydoc
import sys
import operator
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.schema import Table, MetaData
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.exc import NoSuchTableError
from sqlalchemy import func
from model import Instituicao, Grau, Curso, CursoInstituicao, Base
from xlrd import open_workbook
from codigos import *
from graph import *

"""
Declaração de constantes indicadores da posição dos items
no ficheiro cna131fresultados
"""
COD_INSTITUICAO = 0
COD_CURSO = 1
NOME_INSTITUICAO = 2
NOME_CURSO = 3
GRAU = 4
VAGAS_INICIAIS = 5
COLOCADOS = 6
NOTA_ULTIMO = 7
VAGAS_SOBRANTES = 8

"""
	Este metodo escreve num ficheiro CSV linha a linha uma lista passada por argumento
"""
def writeinCSVfile(filename, dataList):
    csvWrite = csv.writer(open(filename, 'w'))
    for run in dataList:
        csvWrite.writerow(run)


engine = create_engine('sqlite:///cna131fresultadosdb.db', echo=False)
Session = sessionmaker(bind=engine)
session = Session()

Base.metadata.create_all(engine)
"""
    Abre uma ligação a base de dados
    Criação de um objecto que gere a base de dados
    Atraves do módulo model.py cria as tabelas
"""
def populateDatabase():
    """
        Nesta função é feita a leitura do ficheiro cna131fresultados.xls, com permissão de leitura
        é efectuado o preenchimento da base de dados, cna131fresultadosdb, sendo verificado
        se existem elementos duplicados, utilização de exceções.
    """

    wb = open_workbook('cna131fresultados.xls', 'r')
    sheet = wb.sheet_by_index(0)

    for row in range(3, 1090): 
    
        cod_instituicao = sheet.cell(row, COD_INSTITUICAO).value
        cod_curso = sheet.cell(row, COD_CURSO).value
        nome_instituicao = sheet.cell(row, NOME_INSTITUICAO).value
        nome_curso = sheet.cell(row, NOME_CURSO).value
        nome_grau = sheet.cell(row,GRAU).value
        vagas_iniciais = str(sheet.cell(row, VAGAS_INICIAIS).value)
        colocados = str(sheet.cell(row, COLOCADOS).value)
        nota_ultimo = str(sheet.cell(row, NOTA_ULTIMO).value)
        vagas_sobrantes = str(sheet.cell(row, VAGAS_SOBRANTES).value)

        grau = Grau(nome_grau.upper())
        instituicao = Instituicao(cod_instituicao, nome_instituicao)
        curso = Curso(cod_curso, nome_curso, grau.cod_grau)

        try:
            existing = session.query(Grau).filter_by(nome_grau=grau.nome_grau).one()
            curso.cod_grau = existing.cod_grau
        except NoResultFound:
            session.add(grau)
            curso.cod_grau = session.query(Grau).filter_by(nome_grau=grau.nome_grau).one().cod_grau

        try:
            existing = session.query(Curso).filter_by(cod_curso=curso.cod_curso).one()
        except NoResultFound:
            session.add(curso)
            
        try:
            existing = session.query(Instituicao).filter_by(cod_instituicao=instituicao.cod_instituicao).one()
        except NoResultFound:
            session.add(instituicao)


        session.add(CursoInstituicao(instituicao.cod_instituicao, curso.cod_curso, vagas_iniciais, colocados, nota_ultimo, vagas_sobrantes))

    session.commit()
    
if(session.query(Curso).count() == 0):
    """
        Verifica a existencia de dados na tabela curso.
        Caso não existam dados, vai preencher a base de dados.
    """
    populateDatabase()
    print "Base de dados preenchida com Sucesso!"
else:
    print "Base de dados já preenchida!"
  

"""
Lê e processa os dados da base de dados "cna131fresultadosdb.db"
de forma a obter o número de colocados por instituição.
É criada uma lista ordenada de forma Decrescente pelo número de colocados.
É escrito num ficheiro CSV a informação da lista e gerado o gráfico em formato pdf.
"""
numColocados = 0
listaNumColocados = []
for instituicao in session.query(Instituicao):
    for alunosInstituicao in session.query(CursoInstituicao).filter_by(cod_instituicao = instituicao.cod_instituicao):
        numColocados += alunosInstituicao.colocados        
        listaNumColocados.append((instituicao.nome_instituicao.encode('utf-8'), numColocados))
    numColocados = 0
    listaNumColocados = sorted(listaNumColocados, reverse=True, key=operator.itemgetter((1)))
writeinCSVfile('ColocadosInstituicao.csv', listaNumColocados)
plotGraph(listaNumColocados, 'Colocados Institicao'.decode('utf-8'), 'AlunosColocadosInstituicao.pdf')

"""
Lê e processa os dados da base de dados "cna131fresultadosdb.db"
de forma a obter o número de colocados por distrito.
É criada uma lista ordenada de forma Decrescente pelo número de colocados.
É escrito num ficheiro CSV a informação da lista e gerado o gráfico em formato pdf.
"""
numColocadosDistrito = 0
numTotalColocados = 0.0
lstColocadosDistrito = []
for key, value in DISTRITOS.items():
    for alunosInstituicao in session.query(CursoInstituicao).filter(CursoInstituicao.cod_instituicao.in_(value)):
        numColocadosDistrito += alunosInstituicao.colocados
        numTotalColocados += alunosInstituicao.colocados
    lstColocadosDistrito.append((key, numColocadosDistrito))    
    numColocadosDistrito = 0
    lstColocadosDistrito = sorted(lstColocadosDistrito, reverse=True, key=operator.itemgetter((1)))
writeinCSVfile('ColocadosPorDistrito.csv', lstColocadosDistrito)
plotGraph(lstColocadosDistrito,'Colocados Por Instituicao'.decode('utf-8'), 'AlunosColocadosDistrito.pdf')

"""
Calculo da Permilagem dos alunos por distrito
É criada uma lista ordenada de forma Decrescente.
É escrito num ficheiro CSV a informação da lista e gerado o gráfico em formato pdf.
"""
lstPermilagem = []
for permilagem in lstColocadosDistrito:
    calculoPermilagem = (1000 * permilagem[1]) / numTotalColocados
    lstPermilagem.append((permilagem[0], round(calculoPermilagem, 3)))
    lstPermilagem = sorted(lstColocadosDistrito, reverse=True, key=operator.itemgetter((1)))
writeinCSVfile('Permilagem.csv', lstPermilagem)
plotGraph(lstPermilagem, 'Permilagem'.decode('utf-8'), 'permilagemColodosDist.pdf')

"""
Lê e processa os dados da base de dados "cna131fresultadosdb.db"
de forma a obter o número vagas sobrantes por instituicao.
É criada uma lista ordenada de forma Decrescente pelo número de colocados.
É escrito num ficheiro CSV a informação da lista e gerado o gráfico em formato pdf.
"""
numVagasSobrantes = 0
lstVagasSobrantes = []
for instituicao in session.query(Instituicao):
    for vagasInstituicao in session.query(CursoInstituicao).filter_by(cod_instituicao = instituicao.cod_instituicao):
        numVagasSobrantes += vagasInstituicao.vagas_sobrantes
    lstVagasSobrantes.append((instituicao.nome_instituicao.encode('utf-8'), numVagasSobrantes))
    numVagasSobrantes = 0
    lstVagasSobrantes = sorted(lstVagasSobrantes, reverse=True, key=operator.itemgetter((1)))
writeinCSVfile('VagasSobrantes.csv', lstVagasSobrantes)
plotGraph(lstVagasSobrantes, 'Vagas Sobrantes por Instituição'.decode('utf-8'), 'VagasSobrantesInstiuicao.pdf')


"""
Lê e processa os dados da base de dados "cna131fresultadosdb.db"
de forma a obter o número de vagas sobrantes por distrito.
É criada uma lista ordenada de forma Decrescente pelo número de colocados.
É escrito num ficheiro CSV a informação da lista e gerado o gráfico em formato pdf.
"""
numVagasDistrito = 0
vagasDistrito = []
for key, value in DISTRITOS.items():
    for vagasInstituicao in session.query(CursoInstituicao).filter(CursoInstituicao.cod_instituicao.in_(value)):
        numVagasDistrito += vagasInstituicao.vagas_sobrantes
    vagasDistrito.append((key, numVagasDistrito))
    numVagasDistrito = 0
    vagasDistrito = sorted(vagasDistrito, reverse=True, key=operator.itemgetter((1)))
writeinCSVfile('VagasDistrito.csv', vagasDistrito)
plotGraph(vagasDistrito, 'Vagas Sobrantes Por Distrito'.decode('utf-8'), 'VagasSobrantesDistrito.pdf')

"""
Lê e processa os dados da base de dados "cna131fresultadosdb.db"
de forma a obter o calculo da percentagem dos alunos colocados por instituicao
em relação a todos os alunos colocados.
É criada uma lista ordenada de forma Decrescente pelo número de colocados.
É escrito num ficheiro CSV a informação da lista e gerado o gráfico em formato pdf.
"""
numTotalColocados = 0.0
numTotalColInstituicao = 0
colocadosInstituicao = []
for instituicao in session.query(Instituicao):
    numTotalColInstituicao = 0
    for alunosInstituicao in session.query(CursoInstituicao).filter_by(cod_instituicao = instituicao.cod_instituicao):
        numTotalColocados += alunosInstituicao.colocados
        numTotalColInstituicao += alunosInstituicao.colocados
    colocadosInstituicao.append((instituicao.nome_instituicao, numTotalColInstituicao))

calculoPercentagem = []
for colInstituicao in colocadosInstituicao:
    calcPercentagem = (colInstituicao[1] * 100) / numTotalColocados
    calculoPercentagem.append((colInstituicao[0].encode('utf-8'), round(calcPercentagem,2)))
    percentagem1 = sorted(calculoPercentagem, reverse=True, key=operator.itemgetter((1)))
writeinCSVfile('Percentagem.csv', calculoPercentagem)
plotGraph(calculoPercentagem, 'Percentagem Colocados por Institução'.decode('utf-8'), 'percentagemColocadosInstRelTodsAlunos.pdf')
